<?php


namespace EchoPHP\Redis;

use EchoPHP\Facades\Log;
use RuntimeException;
use Redis;
use Exception;

class PhpRedisConnector {

    /**
     * 简历redis链接
     * @param array $config
     * @return Redis
     */
    public function connect(array $config) {
        $redis = new Redis();
        //建立与服务端的链接
        if (!$this->establishConnection($redis, $config)) {
            throw new RuntimeException('redis链接失败');
        }

        return $redis;
    }

    /**
     * 链接redis
     * @param Redis $client
     * @param array $config
     * @return bool
     */
    protected function establishConnection($client, array $config) {
        foreach ($config as $item) {
            try {
                $persistent = isset($item['persistent']) && $item['persistent'] ? true : false;
                $connectParameters = [
                    $item['host'],
                    $item['port'],
                    $item['timeout'] ?? 2,
                    $persistent ? ($item['persistent_id'] ?? null) : null,
                ];
                $client->{($persistent ? 'pconnect' : 'connect')}(...$connectParameters);

                //验证密码
                if (!empty($item['password']) && !$client->auth($item['password'])) {
                    Log::error('Redis节点[' . $item['host'] . ':' . $item['port'] . ']密码错误');
                    continue;
                }

                $replication = $client->info('REPLICATION');
                if ($replication['role'] != 'master') {
                    $client->close();
                    continue;
                }

                $database = $item['database'] ?? 0;
                if (!$client->select($database)) {
                    Log::error('Redis节点[' . $item['host'] . ':' . $item['port'] . ']数据库[' . $database . ']选择失败');
                    continue;
                }
                return true;
            } catch (Exception $e) {
                $client->close();
                Log::error('Redis节点[' . $item['host'] . ':' . $item['port'] . ']无法访问');
                continue;
            }
        }
        Log::emergency('Redis 所有节点均已无法访问');
        return false;
    }
}